home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d12
/
du.arc
/
DUENTRY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-10-05
|
7KB
|
272 lines
/* @(#) duentry.c 1.2 90/09/08 14:38:56 */
/*
* Package: du - Enhanced "du" disk usage report generator.
* File: duentry - Scan entries for disk usage.
*
* The "du_entry()" routine provides the disk usage of a filesystem entry.
* To process directories, the "du_dir()" routine will be run recursively.
*
* Sat Sep 8 14:34:56 1990 - Chip Rosenthal <chip@chinacat.Unicom.COM>
* Cleanup for distribution.
* Tue Apr 17 21:50:58 1990 - Chip Rosenthal <chip@chinacat.Unicom.COM>
* Original composition.
*
* Copyright 1990, Unicom Systems Development. All rights reserved.
* See accompanying README file for terms of distribution and use.
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "du.h"
#ifdef M_XENIX
# include <sys/ndir.h>
typedef struct direct DIRENT;
#else
# include <dirent.h>
typedef struct dirent DIRENT;
#endif
static char SccsID[] = "@(#) duentry.c 1.2 90/09/08 14:38:56";
/*
* Local procedures.
*/
BOOL du_dir();
/*
* External procedures.
*/
extern DIR *opendir();
extern DIRENT *readdir();
extern void exit();
/*
* du_entry() - Initiate a disk usage report for a specified filesys entry.
*/
void du_entry(entry)
char *entry; /* name of the entry to check */
{
struct stat sbuf; /* for stat info on this entry */
struct fsinfo *fsinfop; /* for filesys info on this entry */
struct dskusage tot_blocks; /* to accumulate usage of this entry */
/*
* Get the information on this entry.
*/
if ( stat(entry, &sbuf) != 0 ) {
errmssg(ERR_WARN,"couldn't stat '%s'", entry);
return;
}
if ( (fsinfop = fs_getinfo((struct fsinfo *)NULL, &sbuf)) == NULL ) {
errmssg(ERR_WARN,"couldn't get filesystem info for '%s'", entry);
return;
}
switch ( sbuf.st_mode & S_IFMT ) {
case S_IFREG:
set_usage(&tot_blocks, &sbuf, fs_numblocks(fsinfop, &sbuf));
if ( All_entries || Total_only )
print_usage(entry, &tot_blocks);
break;
case S_IFDIR:
if ( chdir(entry) != 0 ) {
errmssg(ERR_WARN,"couldn't chdir to '%s'", entry);
break;
}
if ( du_dir(entry, &sbuf, fsinfop, &tot_blocks) && Total_only )
print_usage(entry, &tot_blocks);
if ( chdir(Curr_dir) != 0 )
errmssg(ERR_ABORT,"couldn't chdir back to '%s'", Curr_dir);
break;
default:
if ( Print_errors ) {
fprintf(stderr, "%s: '%s' is not a file or directory\n",
Progname, entry);
}
return;
}
}
/*
* du_dir() - Scan through a specific directory and report its disk space
* usage. No information is returned. Depending upon certain options,
* this procedure might recursively scan encountered directories, or
* accumulate subdirectory usage in this directory.
*/
BOOL du_dir(dir_name, dir_statp, dir_fsinfop, dir_blocks_p)
char *dir_name; /* pathname to the directory to scan */
struct stat *dir_statp; /* stat information on this directory */
struct fsinfo *dir_fsinfop; /* info on filesystem containing dir */
Reg struct dskusage *dir_blocks_p; /* storage for the usage */
{
Reg DIRENT *dp; /* current entry being checked */
Reg char *ent_basename; /* ptr to basename portion of pathname*/
struct dskusage ent_blocks; /* usage statistics for current entry */
struct stat ent_stat; /* inode info for current entry */
struct fsinfo *ent_fsinfop; /* info on filesys with current entry */
DIR *dirp; /* stream for dir being searched */
char ent_pathname[MAXNAMLEN]; /* full pathname of entry */
long nblocks;
/*
* Setup a buffer to hold the full pathname of the entry being examined.
* We can just place a filename at "ent_basename" to make the full pathname.
*/
ent_basename = strcpy(ent_pathname, dir_name) + strlen(dir_name);
*ent_basename++ = '/';
/*
* Initialize the block count with the usage by the directory itself.
*/
set_usage(dir_blocks_p, dir_statp, fs_numblocks(dir_fsinfop, dir_statp));
/*
* Open up the directory so we can scan it.
*/
if ( (dirp=opendir(".")) == NULL ) {
errmssg(ERR_WARN,"couldn't open dir '%s'", dir_name);
return FALSE;
}
/*
* Go through each entry in the directory.
*/
while ( (dp=readdir(dirp)) != NULL ) {
/*
* Skip the "." and ".." entries.
*/
if (
dp->d_name[0] == '.' && (
dp->d_name[1] == '\0' ||
( dp->d_name[1] == '.' && dp->d_name[2] == '\0' )
)
) {
continue;
}
/*
* Create the full pathname to this entry.
*/
(void) strcpy(ent_basename, dp->d_name);
/*
* Get the information on this entry.
*/
if ( stat(ent_basename, &ent_stat) != 0 ) {
errmssg(ERR_WARN,"couldn't stat '%s'", ent_pathname);
continue;
}
/*
* How we process this entry depends upon what type it is.
*/
switch ( ent_stat.st_mode & S_IFMT ) {
/*
* For files, accumulate the disk usage into the directory total.
*/
case S_IFREG:
/*
* See if we want to process this file.
*/
if ( ent_stat.st_nlink > 1 ) {
if ( Skip_links )
break;
if ( Suppress_repeats && fs_linkdone(dir_fsinfop, &ent_stat) )
break;
}
nblocks = fs_numblocks(dir_fsinfop, &ent_stat);
set_usage(&ent_blocks, &ent_stat, nblocks);
add_usage(dir_blocks_p, &ent_blocks);
if ( All_entries )
print_usage(ent_pathname, &ent_blocks);
break;
/*
* For directories, we might need to scan recursively.
*/
case S_IFDIR:
/*
* Check if we are crossing a mount point.
*/
if ( !Cross_filesys && dir_statp->st_dev != ent_stat.st_dev )
break;
/*
* Get the filesystem information on this diretory.
*/
ent_fsinfop = fs_getinfo(dir_fsinfop, &ent_stat);
if ( ent_fsinfop == NULL ) {
errmssg(ERR_WARN,"couldn't get filesystem info for '%s'",
ent_pathname);
break;
}
/*
* If we shouldn't descend into this dir, then just get its size.
*/
if ( !Descend_dirs ) {
nblocks = fs_numblocks(ent_fsinfop, &ent_stat);
set_usage(&ent_blocks, &ent_stat, nblocks);
add_usage(dir_blocks_p, &ent_blocks);
if ( !Total_only )
print_usage(ent_pathname, &ent_blocks);
break;
}
/*
* Go get the usage on this directory.
*/
if ( chdir(ent_basename) != 0 ) {
errmssg(ERR_WARN,"couldn't chdir to '%s'", ent_pathname);
break;
}
if ( du_dir(ent_pathname, &ent_stat, ent_fsinfop, &ent_blocks) ) {
if ( Accum_subdirs )
add_usage(dir_blocks_p, &ent_blocks);
}
if ( chdir("..") != 0 ) {
Print_errors = TRUE;
errmssg(ERR_WARN,"couldn't chdir back to '%s'", dir_name);
exit(1);
}
break;
/*
* Special files are ignored.
*/
default:
break;
}
}
/*
* The current directory is complete.
*/
(void) closedir(dirp);
if ( !Total_only )
print_usage(dir_name, dir_blocks_p);
return TRUE;
}